package com.senmiao.ssm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.senmiao.ssm.constants.OperateLogType;
import com.senmiao.ssm.entity.*;
import com.senmiao.ssm.mapper.*;
import com.senmiao.ssm.service.DoLogService;
import com.senmiao.ssm.utils.IPHelper;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class DoLogServiceImpl implements DoLogService {

    @Resource
    private AdminMapper adminMapper;

    @Resource
    private OperateLogMapper operateLogMapper;

    @Resource
    private EmployeeMapper employeeMapper;

    @Resource
    private OperateLogDetailMapper operateLogDetailMapper;

    @Resource
    private RolePermissionMapper rolePermissionMapper;

    @Resource
    AdminRoleMapper adminRoleMapper;

    @Resource
    RoleMapper roleMapper;

    @Override
    public void saveLoginLog(String account, String ipAddr, boolean loginFailed) {
        // 根据账号获取管理员id
        Admin admin = adminMapper.selectOne(new QueryWrapper<Admin>()
                .eq("account", account).eq("is_delete", 0));
        if (admin != null) {
            // 创建日志对象
            OperateLog operateLog = new OperateLog();
            operateLog.setType(OperateLogType.LOGIN);// 操作类型：登录
            operateLog.setAdminId(admin.getId());
            operateLog.setTableId(admin.getId());
            operateLog.setIp(ipAddr);
            operateLog.setTableName("tb_admin");
            operateLog.setCreateTime(new Date());
            if (loginFailed) {
                // 登录失败日志
                operateLog.setComment("登录失败");
            } else {
                // 登陆成功日志
                operateLog.setComment("登录成功");
            }
            // 保存到数据库
            operateLogMapper.insert(operateLog);
        }
    }

    @Override
    public void saveLogoutLog(Integer adminId, String ipAddr) {
        // 创建日志对象
        OperateLog operateLog = new OperateLog();
        operateLog.setTableName("tb_admin");
        operateLog.setCreateTime(new Date());
        operateLog.setIp(ipAddr);
        operateLog.setComment("登出");
        operateLog.setTableId(adminId);
        operateLog.setAdminId(adminId);
        operateLog.setType(OperateLogType.LOGOUT);
        operateLogMapper.insert(operateLog);
    }

    @Override
    public void saveDeleteLog(List<Integer> employeeIds, String tableName, Integer adminId, String ipAddr) {
        for (Integer employeeId : employeeIds) {
            OperateLog operateLog = new OperateLog();
            operateLog.setTableName(tableName);
            operateLog.setCreateTime(new Date());
            operateLog.setIp(ipAddr);
            operateLog.setComment("删除");
            operateLog.setTableId(employeeId);
            operateLog.setAdminId(adminId);
            operateLog.setType(OperateLogType.DELETE);
            operateLogMapper.insert(operateLog);
        }
    }

    @Override
    public Employee getEmployeeById(Integer recordId) {
        return employeeMapper.selectById(recordId);
    }

    @Override
    public void updateLog(Integer recordId, Integer adminId, String tableName, Object pre, Object after) {
        // 插入日志表一条修改日志记录
        OperateLog operateLog = new OperateLog();
        operateLog.setType(OperateLogType.UPDATE);
        operateLog.setAdminId(adminId);
        operateLog.setComment("修改");
        operateLog.setTableId(recordId);
        operateLog.setIp(IPHelper.getIpAddr());
        operateLog.setTableName(tableName);
        operateLog.setCreateTime(new Date());
        // 保存到日志表
        operateLogMapper.insert(operateLog);
        Long operateLogId = operateLog.getId();
        if (operateLogId == null) {
            // 进入到这里面说明这次日志记录到数据库失败，则后面的不执行
            return;
        }
        // 获取员工实体字段
        Field[] fields = pre.getClass().getDeclaredFields();
        // 对比修改前后对象，将有变化的记录进日志表，除去创建时间和修改时间
        for (Field field : fields) {
            String fieldName = field.getName();
            if (fieldName.equals("createTime") || fieldName.equals("modifiedTime")) {
                continue;
            }
            try {
                // 允许暴力反射
                field.setAccessible(true);
                Object old = field.get(pre);
                Object now = field.get(after);
                if (!old.equals(now)) {
                    // 若该字段两个对象不一致，表明该字段有修改
                    OperateLogDetail detail = new OperateLogDetail();
                    detail.setLogId(operateLogId);
                    detail.setCreateTime(new Date());
                    detail.setFieldName(fieldName);
                    detail.setOldValue(old + "");
                    detail.setCurrentValue(now + "");
                    // 保存到数据库
                    operateLogDetailMapper.insert(detail);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取某个角色有的权限的id
     *
     * @param roleId
     * @return
     */
    @Override
    public List<Integer> getPermissionIdsOfRole(Integer roleId) {
        List<RolePermission> rolePermissions = rolePermissionMapper.selectList(new QueryWrapper<RolePermission>().eq("role_id", roleId).eq("is_delete", 0));
        ArrayList<Integer> permissionIds = new ArrayList<>(rolePermissions.size());
        rolePermissions.forEach(e -> permissionIds.add(e.getId()));
        return permissionIds;
    }

    @Override
    public void authorizeLog(Integer adminId, Integer roleId, List<Integer> permissionsIdsOfRolePre, List<Integer> permissionsIdsOfRoleAfter) {
        // 新增的权限
        ArrayList<Integer> newPermissionIds = new ArrayList<>(permissionsIdsOfRoleAfter);
        newPermissionIds.removeAll(permissionsIdsOfRolePre);

        // 删除的权限
        ArrayList<Integer> deletePermissionIds = new ArrayList<>(permissionsIdsOfRolePre);
        deletePermissionIds.removeAll(permissionsIdsOfRoleAfter);

        // 记录到日志表
        for (Integer newPermissionId : newPermissionIds) {
            OperateLog operateLog = new OperateLog();
            operateLog.setCreateTime(new Date());
            operateLog.setTableName("tb_role_permission");
            operateLog.setIp(IPHelper.getIpAddr());
            operateLog.setTableId(roleId);
            operateLog.setComment(roleId + ":角色新增权限:" + newPermissionId);
            operateLog.setAdminId(adminId);
            operateLog.setType(OperateLogType.UPDATE);
            operateLogMapper.insert(operateLog);
        }
        for (Integer deletePermissionId : deletePermissionIds) {
            OperateLog operateLog = new OperateLog();
            operateLog.setCreateTime(new Date());
            operateLog.setTableName("tb_role_permission");
            operateLog.setIp(IPHelper.getIpAddr());
            operateLog.setTableId(roleId);
            operateLog.setComment(roleId + ":角色失去权限:" + deletePermissionId);
            operateLog.setAdminId(adminId);
            operateLog.setType(OperateLogType.UPDATE);
            operateLogMapper.insert(operateLog);
        }
    }

    @Override
    public void insertLog(Integer adminId, String tableName) {
        OperateLog operateLog = new OperateLog();
        operateLog.setAdminId(adminId);
        operateLog.setTableName(tableName);
        operateLog.setType(OperateLogType.CREATE);
        operateLog.setTableId(0);
        operateLog.setComment("表" + tableName + "新增一条数据");
        operateLog.setIp(IPHelper.getIpAddr());
        operateLog.setCreateTime(new Date());
        operateLogMapper.insert(operateLog);
    }

    @Override
    public void queryLog(Integer adminId, String tableName) {
        Admin admin = adminMapper.selectById(adminId);
        if (admin == null) {
            return;
        }
        OperateLog operateLog = new OperateLog();
        String comment = "管理员：" + admin.getUsername() + "查看了日志";
        operateLog.setComment(comment);
        operateLog.setIp(IPHelper.getIpAddr());
        operateLog.setCreateTime(new Date());
        operateLog.setType(OperateLogType.QUERY);
        operateLog.setTableName(tableName);
        operateLog.setAdminId(adminId);
        operateLogMapper.insert(operateLog);
    }

    @Override
    public Integer getRoleIdOfAdmin(Integer adminIdUpdate) {
        List<AdminRole> adminRoles = adminRoleMapper.selectList(new QueryWrapper<AdminRole>().eq("admin_id", adminIdUpdate).eq("is_delete", 0));
        if (adminRoles.size() == 0) {
            return 0;
        }
        return adminRoles.get(0).getRoleId();
    }

    @Override
    public void changeAdminRoleLog(Integer adminId, Integer adminIdUpdate, Integer roleIdPre, Integer roleIdAfter) {
        Role rolePre = roleMapper.selectById(roleIdPre);
        Role roleAfter = roleMapper.selectById(roleIdAfter);
        String comment = null;
        if (rolePre != null && roleAfter != null){
            comment = "角色从" + rolePre.getName() + "变更为"+ roleAfter.getName();
        }
        OperateLog operateLog = new OperateLog();
        operateLog.setAdminId(adminId);
        operateLog.setTableName("tb_admin_role");
        operateLog.setTableId(adminIdUpdate);
        operateLog.setType(OperateLogType.UPDATE);
        operateLog.setCreateTime(new Date());
        operateLog.setIp(IPHelper.getIpAddr());
        operateLog.setComment(comment);
        operateLogMapper.insert(operateLog);
    }
}